import {TopDesign} from "./context";
import {useEffect, useLayoutEffect} from "react";
import {useOnce} from "./hook";

/**
 * 创建一个基于hook的函数
 * @author  韦胜健
 * @date    2021/4/4 19:17
 */
export function createHookFunction<FN extends (...args: any) => any>(name: string, fn: FN): FN {
    return ((...args: any[]) => {
        if (!TopDesign.ctx) {throw new Error(`只能在setup函数执行的时候执行${name}函数`)}
        return fn(...args)
    }) as FN
}

/**
 * 在setup函数中使用hook
 * @author  韦胜健
 * @date    2021/4/4 19:17
 */
export const useHooksOnDesign = createHookFunction('useHooksOnDesign', function <T extends () => any>(cb: T): { current: ReturnType<T> } {
    return TopDesign.ctx!.useHook(cb)
})

/**
 * 挂载之前
 * @author  韦胜健
 * @date    2021/4/4 19:17
 */
export const onBeforeMount = createHookFunction('onBeforeMount', (cb: () => (void | (() => void) | any)) => {
    useHooksOnDesign(() => {
        useLayoutEffect(() => {
            const returnValue = cb()
            return typeof returnValue === "function" ? returnValue : undefined
        }, [])
    })
})

/**
 * 卸载之前
 * @author  韦胜健
 * @date    2021/4/4 19:17
 */
export const onBeforeUnmount = createHookFunction('onBeforeUnmount', (cb: () => void) => {
    useHooksOnDesign(() => {
        useLayoutEffect(() => {
            return cb
        }, [])
    })
})

/**
 * 挂载之后
 * @author  韦胜健
 * @date    2021/4/4 19:18
 */
export const onMounted = createHookFunction('onMounted', (cb: () => (void | (() => void) | any)) => {
    useHooksOnDesign(() => {
        useEffect(() => {
            const returnValue = cb()
            return typeof returnValue === "function" ? returnValue : undefined
        }, [])
    })
})

/**
 * 卸载之后
 * @author  韦胜健
 * @date    2021/4/4 19:18
 */
export const onUnmounted = createHookFunction('onUnmounted', (cb: () => void) => {
    useHooksOnDesign(() => {
        useEffect(() => {
            return cb
        }, [])
    })
})

/**
 * 更新之后
 * @author  韦胜健
 * @date    2021/4/4 19:18
 */
export const onUpdated = createHookFunction('onUpdated', (cb: () => (void | (() => void) | any)) => {
    useHooksOnDesign(() => {
        useEffect(() => {
            const returnValue = cb()
            return typeof returnValue === "function" ? returnValue : undefined
        })
    })
})

/**
 * 更新前
 * @author  韦胜健
 * @date    2021/4/4 20:04
 */
export const onBeforeUpdate = createHookFunction('onBeforeUpdate', (cb: () => (void | (() => void) | any)) => {
    useHooksOnDesign(() => {
        return cb()
    })
})

/*---------------------------------------onBeforeRender-------------------------------------------*/

export function createUseBeforeRenderManager() {
    return useOnce(() => {
        const listeners: (() => void)[] = []
        return {
            useBeforeRenderManager: {
                listeners,
                useBeforeRender: (cb: () => void) => listeners.push(cb),
                execBeforeRender: () => listeners.forEach(cb => cb()),
            },
        }
    })
}

export const onBeforeRender = createHookFunction('onBeforeRender', (cb: () => void) => {
    TopDesign.ctx!.useBeforeRender(cb)
})